﻿using GTMC.Interface.Plugin;
using GTMC.Model;
using Leeder.Enum;
using Leeder.GTMC.Plugin;
using Leeder.Logger;
using Leeder.Model;
using Leeder.Model.Handler;
using Leeder.Plugin;
using Leeder.Resource;
using Leeder.Util;
using Newtonsoft.Json;
using ScanConfirm.Business;
using ScanConfirm.Comm;
using ScanConfirm.Enum;
using ScanConfirm.Model;
using ScanConfirm.PdaServer;
using SqlSugar;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace ScanConfirm.Handle
{
    public class ScanConfirmHandler
    {
        public ConfigModel Config { get; set; }
        public SysSetupModel SysSetup { get; set; }
        public List<IoCarConfigModel> IoCarConfigs { get; set; }
        public List<QueueInfoModel> CurrentWorkQueues { get; set; }

        /// <summary>
        /// 品番/记号等同列表
        /// </summary>
        public List<PartsCodeEquateModel> PartsCodeEquteList { get; set; }

        public UserModel User { get; set; }
        /// <summary>
        /// JSON文件 保存/加载 路径
        /// </summary>
        public string Path = System.Windows.Forms.Application.StartupPath + "\\";
        private LogOperate LogObj => Log.GetLogger(this.GetType());
        private QueueInfoBLL queueInfoBLL = new QueueInfoBLL();
        private ScanRecordBLL scanRecordBLL = new ScanRecordBLL();
        private PartsSetupBLL partsSetupBLL = new PartsSetupBLL();
        private PartsCodeEquateBLL partsCodeEquateBLL = new PartsCodeEquateBLL();
        private ReceivesMessageBLL receivesMessageBLL = new ReceivesMessageBLL();
        private ProductionModelsBLL productionModelsBLL = new ProductionModelsBLL();
        private CarTypeBLL carTypeBLL = new CarTypeBLL();
        private SysSetupBLL sysSetupBLL = new SysSetupBLL();
        private UserBLL userBLL = new UserBLL();
        private IOCardHandler iOCardHandler;
        private BarcodeHandler barcodeHandler;
        private BarcodeHandler rfidHandler;
        private IPokayoke iPokayoke;
        private TriaHandler triaHandler;
        AutoResetEvent AtresetEvent = new AutoResetEvent(false);

        //PDA服务
        EgTcpServerEquipmet egTcpServer;

        private const string CloseAllCMD = "001";
        private const string ResetCMD = "002";
        private const string AwaitCMD = "003";
        private const string AlarmCMD = "004";
        private const string CompleteCMD = "005";
        private const string PokayokeJudgeCMD = "008";
        private const string PokayokeStartCMD = "010";
        private const string PokayokeOkCMD = "012";

        private List<PartsSetupModel> PartsSetupList = new List<PartsSetupModel>();

        public List<DeviceModel> DeviceList = new List<DeviceModel>();

        public ConcurrentQueue<string> TriaQueue { get; set; }

        public event Action<List<QueueInfoModel>> OnWorkQueueChange;
        public event Action<string,bool> OnScanInput;
        public event Action<List<DeviceModel>> OnDeviceChange;

        /// <summary>
        /// 消息通知事件
        /// </summary>
        public event Action<string, MessageType> MesgNotificationEvent;

        /// <summary>
        /// 异常时间(前端获取数据异常)
        /// </summary>
        DateTime ExceptionTime = new DateTime();
        /// <summary>
        /// 数据库连接状态
        /// </summary>
        private bool SqlServerConnectState = false;

        /// <summary>
        /// 当POK接收到数据时为1，防止判定信号及开始信号出错
        /// </summary>
        private bool isPokayokaReceiveProdInsNotify = false; 

        /// <summary>
        /// 单例模式
        /// </summary>
        private static ScanConfirmHandler instance = new ScanConfirmHandler();
        public static ScanConfirmHandler getInstance()
        {
            if (instance == null)
                instance = new ScanConfirmHandler();
            return instance;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        private ScanConfirmHandler(){ }

        public bool Login(string userName, string password)
        {
            var user = userBLL.Login(userName, password);
            if(user != null)
            {
                User = user;
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public bool Init()
        {
            MesgNotificationEvent?.BeginInvoke("系统初始化...", MessageType.Info, null, null);
            lockObj = new object();
            lockObj_pok = new object();
            SysSetup = sysSetupBLL.GetModel();
            if(SysSetup == null)
            {
                return false;
            }
            Config = LoadConfig();
            IoCarConfigs = LoadConfig_IoCard();
            if (Config == null)
            {
                return false;
            }
            PartsSetupList = partsSetupBLL.GetModelAll();

            PartsCodeEquteList = partsCodeEquateBLL.GetModelList();

            DeviceList.Add(new DeviceModel { Name = "IO卡", State = false });

            Task.Run(async delegate
            {
                if (InitIOCard(out iOCardHandler, IoCarConfigs, Config.IoCarCom))
                {
                    DeviceList.Where(x => x.Name == "IO卡").FirstOrDefault().State = true;
                    LogObj.Info("IO卡连接成功！");
                    MesgNotificationEvent?.BeginInvoke("IO卡连接成功！", MessageType.Info, null, null);
                    IoCardInitAction();
                    OnDeviceChange?.BeginInvoke(DeviceList, null, null);
                }
                else
                {
                    LogObj.Error("IO卡连接失败！");
                    MesgNotificationEvent?.BeginInvoke("IO卡连接失败！", MessageType.Error, null, null);
                }
            });

            if (SysSetup.InputType == "扫码枪")
            {
                DeviceList.Add(new DeviceModel { Name = "扫码枪", State = false });
                if(InitScanner(out barcodeHandler, Config.ScanCom))
                {
                    DeviceList.Where(x => x.Name == "扫码枪").FirstOrDefault().State = true;
                    LogObj.Info("扫码枪连接成功！");
                    MesgNotificationEvent?.BeginInvoke("扫码枪连接成功！", MessageType.Info, null, null);
                    OnDeviceChange?.BeginInvoke(DeviceList, null, null);
                }
                else
                {
                    LogObj.Error("扫码枪连接失败！");
                    MesgNotificationEvent?.BeginInvoke("扫码枪连接失败！", MessageType.Error, null, null);
                }
            }
            else if (SysSetup.InputType == "PDA")
            {
                DeviceList.Add(new DeviceModel { Name = "PDA", State = false });
                if(CreatePdaConnect(Config.PdaServerIP,Config.PdaServerPort.ToString()))
                {
                    LogObj.Info("PDA服务开启成功！");
                    MesgNotificationEvent?.BeginInvoke("PDA服务开启成功！", MessageType.Info, null, null);
                }
                else
                {
                    LogObj.Error("PDA服务开启失败！");
                    MesgNotificationEvent?.BeginInvoke("PDA服务开启失败！", MessageType.Error, null, null);
                }
            }

            //初始化RFID读写器
            DeviceList.Add(new DeviceModel { Name = "RFID", State = false });
            if (InitRFID(out rfidHandler, Config.RfidCom))
            {
                DeviceList.Where(x => x.Name == "RFID").FirstOrDefault().State = true;
                LogObj.Info("RFID读写器连接成功！");
                MesgNotificationEvent?.BeginInvoke("RFID读写器连接成功！", MessageType.Info, null, null);
                OnDeviceChange?.BeginInvoke(DeviceList, null, null);
            }
            else
            {
                LogObj.Error("RFID读写器连接失败！");
                MesgNotificationEvent?.BeginInvoke("RFID读写器连接失败！", MessageType.Error, null, null);
            }

            Thread.Sleep(100);
            GetQueueInfo(SysSetup.QueueCount, false);
            Thread.Sleep(500);


            if (SysSetup.ProductionGuideType == "POKAYOKE")
            {
                DeviceList.Add(new DeviceModel { Name = "POKAYOKE", State = false });

                if (InitPokayoka(out iPokayoke, Config.PokayokaCom))
                {
                    if (SysSetup.WorkType == "batch")
                    {
                        //RefreshQueueInfo();
                        //屏蔽掉主动获取POKAYOKE队列20240919
                        GetQueueInfo();
                    }
                    else
                    {

                    }
                }
                else
                {
                    LogObj.Error("POKAYOKE连接失败！");
                    MesgNotificationEvent?.BeginInvoke("POKAYOKE连接失败！", MessageType.Error, null, null);
                }
            }
            else if (SysSetup.ProductionGuideType == "TRIA")
            {
                TriaQueue = new ConcurrentQueue<string>();
                TriaDataQueueResolve();

                DeviceList.Add(new DeviceModel { Name = "TRIA", State = false });
                if(InitTria(out triaHandler,Config.LogicLength,Config.TriaIp,Config.TriaPort))
                {
                    DeviceList.Where(x => x.Name == "TRIA").FirstOrDefault().State = true;
                    LogObj.Info("TRIA服务开启成功！");
                    MesgNotificationEvent?.BeginInvoke("TRIA服务开启成功！", MessageType.Info, null, null);
                }
                else
                {
                    LogObj.Error("TRIA服务开启失败！");
                    MesgNotificationEvent?.BeginInvoke("TRIA服务开启失败！", MessageType.Error, null, null);
                }
            }
            MesgNotificationEvent?.BeginInvoke("系统初始化完成", MessageType.Info, null, null);

            return true;
        }

        /// <summary>
        /// API初始化
        /// </summary>
        /// <returns></returns>
        public bool ApiInit()
        {
            lockObj = new object();
            //SysSetup = sysSetupBLL.GetModel();
            //if (SysSetup == null)
            //{
            //    return false;
            //}
            Config = LoadConfig();
            //PartsSetupList = partsSetupBLL.GetModelAll();
            //GetQueueInfo(SysSetup.QueueCount, true);
            return true;
        }

        /// <summary>
        /// 初始化端末
        /// </summary>
        /// <returns></returns>
        public bool TriaInit()
        {
            lockObj = new object();
            SysSetup = sysSetupBLL.GetModel();
            if (SysSetup == null)
            {
                return false;
            }
            Config = LoadConfig();
            PartsSetupList = partsSetupBLL.GetModelAll();
            if (SysSetup.ProductionGuideType == "TRIA")
            {
                InitTria(out triaHandler, Config.LogicLength, Config.TriaIp, Config.TriaPort);
            }
            return true;
        }

        /// <summary>
        /// 初始化POKAYOKA
        /// </summary>
        /// <param name="ipoka"></param>
        /// <param name="comm"></param>
        /// <returns></returns>
        public bool InitPokayoka(out IPokayoke ipoka, string comm)
        {
            try
            {
                ipoka = PokayokeInstance.GetInstance(comm);
                ipoka.OnDataReceive += Pokayoka_DataReceive;
                ipoka.OnReceiveProdInsNotify += Pokayoka_OnReceiveProdInsNotify;
                ipoka.Start();
                return true;
            }
            catch(Exception ex)
            {
                LogObj.Error("初始化POKAYOKA失败：" + ex.Message);
                ipoka = default;
                return false;
            }
        }

        /// <summary>
        /// 创建PDA连接服务
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public bool CreatePdaConnect(string ip, string port)
        {
            egTcpServer = new EgTcpServerEquipmet("LSA39A");
            egTcpServer.EventSetUivalue += TcpServerOutput;
            egTcpServer.pdaScanResultOutput += pdaScanResultHandler;
            egTcpServer.PdaRequestEvent += PdaRequest;
            egTcpServer.PdaScanEvent += CheckCode;
            egTcpServer.PdaReSetEvent += PdaReSet;
            return egTcpServer.CreateSocketServer(port);
        }

        /// <summary>
        /// 接收PDA服务连接事件信息
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        private void TcpServerOutput(string name, string value)
        {
            if(value != "recvShow" && !value.Contains("接收"))
            {
                var msg = "PDA信息：" + value + "  " + name;
                LogObj.Info(msg);
                MesgNotificationEvent?.BeginInvoke(msg, MessageType.Info, null, null);
            }
            if(!DeviceList.Where(x => x.Name == "PDA").FirstOrDefault().State)
            {
                DeviceList.Where(x => x.Name == "PDA").FirstOrDefault().State = true;
                OnDeviceChange?.BeginInvoke(DeviceList, null, null);
            }
        }

        /// <summary>
        /// PDA扫码结果返回主界面、指示灯提示
        /// </summary>
        /// <param name="pdaSendResult"></param>
        /// <param name="pdaSendData"></param>
        private void pdaScanResultHandler(PdaSendResult pdaSendResult, PdaSendData pdaSendData)
        {
            var msg = "PDA发送信息[Code:" + pdaSendResult.Code + "; Message" + pdaSendResult.Message + ";][funCode:" + pdaSendData.funCode + "; ScanInfo:" + pdaSendData.ScanInfo + "; SendTime" + pdaSendData.SendTime + ";]";
            //LogObj.Info(msg);
            //MesgNotificationEvent?.BeginInvoke(msg, MessageType.Info, null, null);
            if (pdaSendResult.Code == 0)
            {
                CheckCode(pdaSendData.ScanInfo);
            }
            else
            {

            }
        }

        /// <summary>
        /// PDA重设
        /// </summary>
        public void PdaReSet()
        {
            IoCardResetAction();
        }

        /// <summary>
        /// PDA请求
        /// </summary>
        public void PdaRequest()
        {
            var model =GetCurrentWorkModel();
            SendPDA(model);
        }

        /// <summary>
        /// 向PDA推送当前作业车辆
        /// </summary>
        /// <param name="model"></param>
        public void SendPDA(QueueInfoModel model)
        {
            PdaVinData pvd = new PdaVinData();
            pvd.ManyNum = model.Sequence.ToString();
            pvd.CarType = model.VehicleModel;
            pvd.ProgNo = "";
            pvd.SendTime = DateTime.Now;
            pvd.Vin = model.VIN;
            if (SysSetup.CheckType == "PartsCode")
                pvd.Mark = model.PartsCode;
            else if (SysSetup.CheckType == "Mark")
                pvd.Mark = model.Mark;
            pvd.Mark = model.Mark;
            pvd.IsData = true;
            pvd.FunId = 1;
            egTcpServer.SendPDA(pvd);
        }

        /// <summary>
        /// Pokayoka生产指示数据接收
        /// </summary>
        /// <param name="arg1"></param>
        /// <param name="model"></param>
        public void Pokayoka_OnReceiveProdInsNotify(string arg1, PokayokeModel model)
        {
            string msg = $"param1:{arg1},连番:{model.AssemblySequenceNo},车身:{model.BodyNo},VIN:{model.VIN},程序号:{model.ProgramNo}";
            isPokayokaReceiveProdInsNotify = true ;
            LogObj.Info(msg);
            MesgNotificationEvent?.BeginInvoke(msg, MessageType.Info, null, null);
            //根据车型标识码从数据库中获取车型标识，并判断是否存在该车型标识，不存在则返回错误提示
            var partsSet = ProgramNoToMark(model.ProgramNo);
            if(partsSet == null)
            {
                if(SysSetup.WorkType != "batch")
                {
                    Task.Factory.StartNew(async () => {
                        await Task.Delay(2000);
                        IoCardJudgeAction();
                    });
                }
            }
            else
            {
                var carModel = carTypeBLL.GetCarModelByCode(partsSet.CarCode);
                var queue = new QueueInfoModel
                {
                    Sequence = model.AssemblySequenceNo,
                    BodyNum = model.BodyNo,
                    EnqueueDate = DateTime.Now,
                    DeQueueDate = DateTime.Now,
                    CreatedDate = DateTime.Now,
                    VIN = model.VIN,
                    VehicleModel = carModel == null? "":carModel.CarName,
                    IsNEV = false,
                    CarModelCode = partsSet.CarCode,
                    DisplayCode = partsSet.DisplayCode,
                    PartsCode = partsSet.PartsCode,
                    Mark = partsSet.Mark,
                    SyncFlag = 0,
                    IsComplete = false,
                };
                queueInfoBLL.Add(queue);


                CheckSequence();

                if (SysSetup.WorkType == "batch")
                {
                    //RefreshQueueInfoNew(queue);              
                }
                else
                {
                    //刷新
                    RefreshQueueInfo(SysSetup.QueueCount, false);
                }
            }
        }

        /// <summary>
        /// 检查连番是否连续
        /// </summary>
        private void CheckSequence()
        {
            //检查连番有没有连续，不连续则报警，置顶显示红色日志(连番不连续,请联系技术员处理，缺失的连番：100，101)

            var queueList = queueInfoBLL.GetModelListByCount(SysSetup.QueueCount);
            if (!queueList.Any())
                return;

            var lostList = new List<int>();
            if (queueList.Any(x => x.Sequence == 999) && queueList.Any(x => x.Sequence == 0))
            {
                var queueList1 = queueList.Where(x => x.Sequence <= 999 && x.Sequence > 990).ToList();
                if(queueList1.Count()>1)
                {
                    var lostList1 = Check(queueList1);
                    lostList.AddRange(lostList1);
                }
                var queueList2 = queueList.Where(x => x.Sequence < 10).ToList();
                if (queueList2.Count() > 1)
                {
                    var lostList2 = Check(queueList2);
                    lostList.AddRange(lostList2);
                }
            }
            else
            {
                var loseList3 = Check(queueList);
                lostList.AddRange(loseList3);
            }
               
            if (!lostList.Any())
                return;

            //报警
            IoCardErrorAction();

            //置顶显示红色日志
            var msg = string.Format("连番不连续,请联系技术员处理，缺失的连番：{0}", string.Join(",", lostList));
            MesgNotificationEvent?.BeginInvoke(msg, MessageType.TopError, null, null);

        }

        private List<int> Check(List<QueueInfoModel> queueList)
        {
            var lostList = new List<int>();
            //按照连番从小到大排序
            queueList = queueList.OrderBy(x => x.Sequence).ToList();
            var length = queueList.Count();
            var minSquence = queueList[0].Sequence;

            for (var i = 0; i < length - 1; i++)
            {
                var num = queueList[i + 1].Sequence - queueList[i].Sequence;
                if (num == 1)
                    continue;

                for (var j = 1; j < num; j++)
                {
                    lostList.Add(queueList[i].Sequence + j);
                }
            }

            return lostList;
        }

        /// <summary>
        /// Pokayoka数据接收(所有数据)
        /// </summary>
        /// <param name="obj"></param>
        private void Pokayoka_DataReceive(byte[] obj)
        {
            if (obj == null || obj.Length < 1) return;
            string msg = Encoding.UTF8.GetString(obj);
            PokayokaHeartBeat();
            LogObj.Debug(DateTime.Now + "  PI数据:" + msg);

            if (!DeviceList.Where(x => x.Name == "POKAYOKE").FirstOrDefault().State)
            {
                DeviceList.Where(x => x.Name == "POKAYOKE").FirstOrDefault().State = true;
                LogObj.Info("POKAYOKE连接成功！");
                MesgNotificationEvent?.BeginInvoke("POKAYOKE连接成功！", MessageType.Info, null, null);
                OnDeviceChange?.BeginInvoke(DeviceList, null, null);
            }
        }

        /// <summary>
        /// Pokayoka心跳
        /// </summary>
        public void PokayokaHeartBeat()
        {
            AtresetEvent.Set();  //模拟发送心跳数据
        }

        /// <summary>
        /// 根据程序号获取记号配置
        /// </summary>
        /// <param name="programNo"></param>
        /// <returns></returns>
        public PartsSetupModel ProgramNoToMark(int[] programNo)
        {
            var code = programNo[Config.MarkPosition];
            var model = partsSetupBLL.GetPartsSetupByCode(code.ToString());
            if (model != null)
                return model;
            return default;
        }

        /// <summary>
        /// 根据程序号获取品番配置
        /// </summary>
        /// <param name="programNo"></param>
        /// <returns></returns>
        public PartsSetupModel ProgramNoToPartsCode(int[] programNo)
        {
            var code = programNo[Config.PartsCodePosition];
            var model = partsSetupBLL.GetPartsSetupByCode(code.ToString());
            if (model != null)
                return model;
            return default;
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public bool SaveConfig(ConfigModel config)
        {
            var path_config = Path + "Config.json";
            try
            {
                CommonUtil.SaveJson<ConfigModel>(path_config, config);
                var mesg = "用户"+User.LoginName + "保存配置！";
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null,null);
                LogObj.Info(mesg);
                return true;
            }
            catch(Exception ex)
            {
                LogObj.Error("保存配置失败：" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 加载配置
        /// </summary>
        /// <returns></returns>
        public ConfigModel LoadConfig()
        {
            var path_config = Path + "Config.json";
            try
            {
                var congig = CommonUtil.LoadJson<ConfigModel>(path_config, Encoding.UTF8);
                return congig;
            }
            catch (Exception ex)
            {
                //记录异常日志
                LogObj.Error("加载配置失败:" + ex.Message);
                return default;
            }
        }

        /// <summary>
        /// 加载IO卡配置
        /// </summary>
        /// <returns></returns>
        public List<IoCarConfigModel> LoadConfig_IoCard()
        {
            var path_iocardConfig = Path + "Config_IoCard.json";
            try
            {
                var congig = CommonUtil.LoadJson<List<IoCarConfigModel>>(path_iocardConfig, Encoding.UTF8);
                return congig;
            }
            catch (Exception ex)
            {
                //记录异常日志
                LogObj.Error("加载IO卡配置失败:" + ex.Message);
                return default;
            }
        }

        /// <summary>
        /// 获取作业队列
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<QueueInfoModel> GetQueueInfo(int queueLength,bool isApi)
        {
            CurrentWorkQueues = queueInfoBLL.GetModelListByCount(queueLength);
            if(Config.IsQueueChange == 1)
            {
                CurrentWorkQueues = QueueChange(CurrentWorkQueues);
            }

            if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                return CurrentWorkQueues;

            for (int i = 0; i < CurrentWorkQueues.Count; i++)
            {
                if (string.IsNullOrEmpty(CurrentWorkQueues[i].Status) || CurrentWorkQueues[i].Status == "work")
                {
                    CurrentWorkQueues[i].Status = "work";
                    if (SysSetup.InputType == "PDA" && !isApi)
                        SendPDA(CurrentWorkQueues[i]);
                    break;
                }else if (CurrentWorkQueues[i].Status == "unok")
                {
                    CurrentWorkQueues[i].Status = "unok";
                    if (SysSetup.InputType == "PDA" && !isApi)
                        SendPDA(CurrentWorkQueues[i]);
                    break;
                }
            }
            OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            return CurrentWorkQueues;
        }

        /// <summary>
        /// 刷新作业队列,作业定位至最新台车
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<QueueInfoModel> RefreshQueueInfo(int queueLength, bool isApi)
        {
            CurrentWorkQueues = queueInfoBLL.GetModelListByCount(queueLength);

            if (Config.IsQueueChange == 1)
            {
                CurrentWorkQueues = QueueChange(CurrentWorkQueues);
            }

            if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                return CurrentWorkQueues;
            for (int i = 0; i < CurrentWorkQueues.Count; i++)
            {
                if (string.IsNullOrEmpty(CurrentWorkQueues[i].Status) || CurrentWorkQueues[i].Status == "work"|| CurrentWorkQueues[i].Status == "unok")
                {
                    CurrentWorkQueues[i].Status = "pass";
                }
            }
            CurrentWorkQueues[CurrentWorkQueues.Count-1].Status = "work";

            if (SysSetup.InputType == "PDA" && !isApi)
                SendPDA(CurrentWorkQueues[CurrentWorkQueues.Count - 1]);

            OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            return CurrentWorkQueues;
        }

        /// <summary>
        /// 刷新作业队列(新)
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        //public List<QueueInfoModel> RefreshQueueInfoNew(QueueInfoModel model)
        //{
        //    if (CurrentWorkQueues.Count < Config.QueueLength)
        //        CurrentWorkQueues.Add(model);

        //    if (Config.IsQueueChange == 1)
        //    {
        //        CurrentWorkQueues = QueueChange(CurrentWorkQueues);
        //    }

        //    if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
        //        return CurrentWorkQueues;

        //    CurrentWorkQueues[0].Status = "work";

        //    return CurrentWorkQueues;
        //}

        /// <summary>
        /// 前端获取作业队列
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<WorkQueueModel> GetQueueInfoToWeb()
        {
            try
            {
                /***********************获取数据异常后至少隔2分钟后才允许尝试获取数据***********************/
                //TimeSpan ts = DateTime.Now.Subtract(ExceptionTime);
                //double secInterval1 = ts.TotalMinutes;
                //if (secInterval1 < 2)
                //{
                //    return default;
                //}
                /***********************获取数据异常后至少隔2分钟后才允许尝试获取数据***********************/
                if(!SqlServerConnectState)
                {
                    SqlServerConnectState = SqlConnectionState();
                    if(!SqlServerConnectState)
                    {
                        LogObj.Error("数据库连接失败！请检查确认");
                        throw new Exception("数据库连接失败！请检查确认");
                    }
                    SysSetup = sysSetupBLL.GetModel();
                    //PartsSetupList = partsSetupBLL.GetModelAll();
                }

                CurrentWorkQueues = queueInfoBLL.GetModelListByCount(SysSetup.QueueCount);

                if (Config.IsQueueChange == 1)
                {
                    CurrentWorkQueues = QueueChange(CurrentWorkQueues);
                }

                if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                    return default;

                for (int i = 0; i < CurrentWorkQueues.Count; i++)
                {
                    if (string.IsNullOrEmpty(CurrentWorkQueues[i].Status) || CurrentWorkQueues[i].Status == "work")
                    {
                        CurrentWorkQueues[i].Status = "work";
                        break;
                    }
                    else if (CurrentWorkQueues[i].Status == "unok")
                    {
                        CurrentWorkQueues[i].Status = "unok";
                        break;
                    }
                }
                List<WorkQueueModel> list = new List<WorkQueueModel>();
                foreach (var item in CurrentWorkQueues)
                {
                    WorkQueueModel model = new WorkQueueModel();
                    model.Sequence = item.Sequence.ToString("000");
                    model.Mark = item.DisplayCode;
                    if (item.Status == "pass" || item.Status == "ok")
                        model.Status = "1";
                    else if (item.Status == "work")
                        model.Status = "2";
                    else if (item.Status == "unok")
                        model.Status = "-1";
                    else
                        model.Status = "0";
                    list.Add(model);
                }
                return list;
            }
            catch(Exception ex)
            {
                //ExceptionTime = DateTime.Now;
                throw ex;
            }
        }

        /// <summary>
        /// 数据库连接状态
        /// </summary>
        public bool SqlConnectionState()
        {
            var str = ConfigHelper.GetConnectionString(ConfigPath.DbConfigPath, "ScanConfirm");
            ConnectionTestInfo.ConnectionString = EncryptHelper.DecryptText(str);
            return ConnectionTestInfo.ConnectionTest();
        }

        /// <summary>
        /// 重新排列作业队列，连番单数先双数在后，例：1，2，3，4，5，6，7，8，9，10 =>（转换后）1，3，5，7，9，2，4，6，8，10
        /// </summary>
        /// <param name="queues"></param>
        /// <returns></returns>
        private List<QueueInfoModel> QueueChange(List<QueueInfoModel> queues)
        {
            List<QueueInfoModel> list = new List<QueueInfoModel>();
            //先把单数添加进队列
            foreach (var item in queues)
            {
                if (item.Sequence % 2 == 0)
                {
                    //偶数
                }
                else
                {
                    //奇数
                    list.Add(item);
                }
            }
            //再把双数添加进队列
            foreach (var item in queues)
            {
                if (item.Sequence % 2 == 0)
                {
                    //偶数
                    list.Add(item);
                }
                else
                {
                    //奇数
                }
            }
            return list;
        }

        public void RefreshQueueInfo()
        {
            Task.Run(async delegate
            {
               // PokAction();
                queueInfoBLL.SkipALL();
                isRefreshQueueInfo = true;
            });
        }

        bool isRefreshQueueInfo = false;

        public void GetQueueInfo()
        {
                if (SysSetup.ProductionGuideType == "POKAYOKE" && SysSetup.WorkType == "batch")
                {
                    Task.Run(async delegate
                    {
                        while (true)
                        {
                            var queue = queueInfoBLL.GetModelListByCount(200);
                            if (queue.Count < (SysSetup.QueueCount * 3) && DeviceList.Where(x => x.Name == "POKAYOKE").FirstOrDefault().State)
                            {
                                PokAction();
                                //点击队列刷新时，当队列数量大于等于显示数量时自动定位至新队列
                                if(queue.Count >= SysSetup.QueueCount && isRefreshQueueInfo)
                                {
                                    SetLocation(queue[0], SysSetup.QueueCount);
                                    isRefreshQueueInfo = false;
                                }
                            }
                            else
                            {
                                await Task.Delay(5000);
                            }
                        }
                    });
                }
                else
                {

                }
        }

        private object lockObj_pok;
        private void PokAction()
        {
            lock(lockObj_pok)
            {
                isPokayokaReceiveProdInsNotify = false;
                IoCardJudgeAction();
                Thread.Sleep(3000);            //当接收到POK数据时重新给判定信号
                if (isPokayokaReceiveProdInsNotify)
                {
                    IoCardJudgeAction();
                    Thread.Sleep(3000);
                }
                isPokayokaReceiveProdInsNotify = false;
                IoCardStartAction();
                Thread.Sleep(3000);
                IoCardOkAction();
                Thread.Sleep(3000);
            }
        }

        /// <summary>
        /// 根据定位设置新的作业队列
        /// </summary>
        /// <param name="queueLength"></param>
        /// <returns></returns>
        public List<QueueInfoModel> SetLocation(QueueInfoModel model,int queueLength)
        {
            CurrentWorkQueues = queueInfoBLL.SetLocation(model.CreatedDate, queueLength);
            if (CurrentWorkQueues == null || CurrentWorkQueues.Count == 0)
                return CurrentWorkQueues;
            CurrentWorkQueues[0].Status = "work";
            if (SysSetup.InputType == "PDA")
                SendPDA(CurrentWorkQueues[0]);

            var mesg = "用户(" + User.LoginName + ")操作：作业连番定位到" + CurrentWorkQueues[0].Sequence+"("+ CurrentWorkQueues[0].VIN+")";
            MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
            LogObj.Info(mesg);

            OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            return CurrentWorkQueues;
        }

        /// <summary>
        /// 获取当前作业车辆
        /// </summary>
        /// <returns></returns>
        public QueueInfoModel GetCurrentWorkModel()
        {
            return CurrentWorkQueues.Where(x => x.Status == "work" || x.Status == "unok").FirstOrDefault();
        }

        /// <summary>
        /// 强制跳过
        /// </summary>
        /// <returns></returns>
        public void CoerceSkip()
        {
            var item = CurrentWorkQueues.Where(x => x.Status == "work" || x.Status == "unok").FirstOrDefault();
            if (item == null)
                return;
            item.Status = "pass";
            item.CompleteDate = DateTime.Now;
            item.SyncFlag = 2;
            IoCardCompleteAction();

            Task.Factory.StartNew(async () => {
                //await Task.Delay(2000);
                await Task.Delay(3000);
                IoCardJudgeAction();
            });

            var count = CurrentWorkQueues.Where(x => x.Status == null).Count();
            if (count <= 0)
            {
                CurrentWorkQueues.ForEach(x => { x.IsComplete = true; x.SyncFlag = 2; });
                queueInfoBLL.UpdateList(CurrentWorkQueues);
                GetQueueInfo(SysSetup.QueueCount, false);
                return;
            }
            for (int i = 0; i < CurrentWorkQueues.Count; i++)
            {
                if (string.IsNullOrEmpty(CurrentWorkQueues[i].Status) || CurrentWorkQueues[i].Status == "work" || CurrentWorkQueues[i].Status == "unok")
                {
                    CurrentWorkQueues[i].Status = "work";
                    if (SysSetup.InputType == "PDA")
                        SendPDA(CurrentWorkQueues[i]);
                    break;
                }
            }

            var mesg = "用户(" + User.LoginName + ")操作：强制跳过连番！";
            MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
            LogObj.Info(mesg);

            OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
            queueInfoBLL.UpdateList(CurrentWorkQueues);
        }


        /// <summary>
        /// 检验 品番/记号 是否匹配
        /// </summary>
        /// <param name="code"></param>
        public void CheckCode(string code)
        {
            //遍历队列，看看哪些连番跟扫出来的一样。

            var queueList = new List<QueueInfoModel>();
            switch(SysSetup.CheckType)
            {
                case "PartsCode":
                    foreach(var p in CurrentWorkQueues)
                    {
                        var codes = new List<string>() { code };
                        codes.AddRange(PartsCodeEquteList.Where(x=>x.PartsCode== code).Select(x=>x.PartsCodeEquate));
                        
                        if((p.Status == "work" || p.Status == "unok") &&(p.PartsCode==code || codes.Contains(p.PartsCode)))
                        {
                            queueList.Add(p);
                            break;
                        }    
                    }
                    break;
                case "Mark":
                    foreach (var p in CurrentWorkQueues)
                    {
                        if ((p.Status == "work" || p.Status == "unok") && p.Mark==code)
                        {
                            queueList.Add(p);
                            break;
                        }
                    }
                    break;
            }
            
            //未匹配到连番
            if (!queueList.Any())
            {
                //找到第一个未完成的连番
                var item = CurrentWorkQueues.Where(x => x.Status == "work" || x.Status == "unok").FirstOrDefault();
                if (item == null)
                    return;

                item.Status = "unok";
                item.SyncFlag = 2;

                queueInfoBLL.Update(item);

                var mes = "连番" + item.Sequence + "(" + item.VIN + ")检验NG";
                MesgNotificationEvent?.BeginInvoke(mes, MessageType.Error, null, null);
                LogObj.Error(mes);

                IoCardErrorAction();
                OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                Thread.Sleep(50);
                OnScanInput?.BeginInvoke(code, false, null, null);
                return;
            }

            //匹配到连番
            OnScanInput?.BeginInvoke(code, true, null, null);
            //连番状态改成作业中
            queueList.ForEach(x => { x.Status = "work"; });
            queueInfoBLL.UpdateList(queueList);

        }

        /// <summary>
        /// 根据条件获取扫描履历
        /// </summary>
        /// <param name="carType"></param>
        /// <param name="sequenceNo"></param>
        /// <param name="vin"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public List<QueueInfoModel> GetQueueInfoHistory(string carType, int sequenceNo, string vin, DateTime? startTime, DateTime? endTime, int pageIndex, int pageSize)
        {
            return default;
        }

        /// <summary>
        /// 新增车型
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool AddCarType(CarTypeModel model)
        {
            var result = carTypeBLL.Add(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：新增车型"+ model.CarName;
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("新增车型失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 删除车型
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool DeleteCarType(CarTypeModel model)
        {
            var result = carTypeBLL.Delete(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：删除车型" + model.CarName;
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("删除车型失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 更新车型
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool UpdateCarType(CarTypeModel model)
        {
            var result = carTypeBLL.Update(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：更新车型" + model.CarName;
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("更新车型失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 查询所有车型配置
        /// </summary>
        /// <returns></returns>
        public List<CarTypeModel> GetCarTypeAll()
        {
            return carTypeBLL.GetModelAll();
        }

        /// <summary>
        /// 新增部品配置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool AddPartsSetup(PartsSetupModel model)
        {
            var result = partsSetupBLL.Add(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：新增部品配置";
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("新增部品配置失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 删除部品配置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool DeletePartsSetup(PartsSetupModel model)
        {
            var result = partsSetupBLL.Delete(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：删除部品配置";
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("删除部品配置失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 更新部品配置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool UpdatePartsSetup(PartsSetupModel model)
        {
            var result = partsSetupBLL.Update(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：更新部品配置";
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("更新部品配置失败！" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 查询所有部品配置
        /// </summary>
        /// <returns></returns>
        public List<PartsSetupModel> GetPartsSetupAll()
        {
            return partsSetupBLL.GetModelAll();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public SysSetupModel GetSysSetup()
        {
            return sysSetupBLL.GetModel();
        }

        /// <summary>
        /// 系统配置更新
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public bool SetSysSetup(SysSetupModel model)
        {
            var result = sysSetupBLL.Update(model);
            if (result.IsSuccess)
            {
                var mesg = "用户(" + User.LoginName + ")操作：系统配置保存";
                MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
                LogObj.Info(mesg);
                return true;
            }
            else
            {
                LogObj.Error("配置保存失败：" + result.Dsca);
                return false;
            }
        }

        /// <summary>
        /// 获取设备状态
        /// </summary>
        public List<DeviceModel> GetDeviceState()
        {
            return default;
        }

        /// <summary>
        /// IO卡初始化
        /// </summary>
        /// <param name="iOCardHandler">IO卡对象</param>
        /// <param name="ioConfigs">IO卡指令配置</param>
        /// <param name="comm">IO卡COM口</param>
        /// <returns></returns>
        private bool InitIOCard(out IOCardHandler iOCardHandler, List<IoCarConfigModel> ioConfigs, string comm)
        {
            try
            {
                //IO卡连接和初始化
                iOCardHandler = new IOCardHandler(comm);
                var AllIOCommand = ioConfigs.Select(x => new IOCardCMDModel
                {
                    ID = x.ID,//主键
                    Code = x.Code,//指令代码
                    Desc = x.Description,//描述
                    InSignal = x.InSignal,//指令对应的入口
                    InState = x.InState,//指令对应的入口状态
                    OutSignal = x.OutSignal,//指令对应的出口
                    OutState = x.OutState,//指令对应的入口状态
                    InHoldTime = x.InHoldTime,//输入持续时间
                    InHTSuccessCommandID = x.InHTSuccessCommandID,//输入持续时间成功后下一步操作（对应主键）
                    InHTFailCommandID = x.InHTFailCommandID,//输入持续时间即使失败也下一步的操作（对应主键）
                    OutHoldTime = x.OutHoldTime,//输出持续时间
                    AfterOutHTCommandID = x.AfterOutHTCommandID//输出时间结束后执行的操作
                }).ToList();
                iOCardHandler.LoadCommand(AllIOCommand);
                iOCardHandler.OnConnectionBreak += IoCarConnectionEvent;
                //iOCardHandler.OnIOCarConnectionBreak += IoCarConnectionEvent;
                iOCardHandler.OnOutSignalFail += IOCardHandler_OnOutSignalFail;
                iOCardHandler.IsInitiativeRequest = true;
                iOCardHandler.Start();
                return true;
            }
            catch (Exception ex)
            {
                iOCardHandler = default;
                LogObj.Error("IO卡初始化失败！" + ex.Message);
                return false;
            }

        }

        /// <summary>
        /// IO卡指令执行错误事件
        /// </summary>
        /// <param name="arg1"></param>
        /// <param name="arg2"></param>
        private void IOCardHandler_OnOutSignalFail(int arg1, bool arg2)
        {
            LogObj.Error("IO卡指令执行错误，错误端口:" + arg1 + "，错误状态:" + arg2);
        }

        /// <summary>
        /// IO卡连接状态变化事件
        /// </summary>
        /// <param name="str"></param>
        private void IoCarConnectionEvent(string str)
        {

        }

        /// <summary>
        /// IO卡连接状态变化事件
        /// </summary>
        private void IoCarConnectionEvent()
        {

        }

        /// <summary>
        /// IO卡输出(初始化)
        /// </summary>
        public void IoCardInitAction()
        {
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(ResetCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(错误)
        /// </summary>
        public void IoCardErrorAction()
        {
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(AlarmCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(完成)
        /// </summary>
        public void IoCardCompleteAction()
        {
            LogInfo($"完成信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(CompleteCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(判定)
        /// </summary>
        public void IoCardJudgeAction()
        {
            LogInfo($"判定信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(PokayokeJudgeCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(开始)
        /// </summary>
        public void IoCardStartAction()
        {
            LogInfo($"开始信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(PokayokeStartCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(OK)
        /// </summary>
        public void IoCardOkAction()
        {
            LogInfo($"OK信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(PokayokeOkCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(作业中)
        /// </summary>
        public void IoCardAwaitAction()
        {
            LogInfo($"作业中信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(AwaitCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(重置)
        /// </summary>
        public void IoCardResetAction()
        {
            LogInfo($"初始化信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteOutput(ResetCMD); } catch (Exception ex) { }
        }

        /// <summary>
        /// IO卡输出(关闭)
        /// </summary>
        public void IoCardCloseAction()
        {
            LogInfo($"关闭信号");
            if (DeviceList.Where(s => s.Name == "IO卡").FirstOrDefault().State)
                try { iOCardHandler.WriteAllOutput(false); } catch (Exception ex) { }
        }

        /// <summary>
        /// 扫码枪初始化
        /// </summary>
        /// <param name="comm">串口号</param>
        private bool InitScanner(out BarcodeHandler barcodeHandler, string comm)
        {
            try
            {
                barcodeHandler = new BarcodeHandler(comm);
                barcodeHandler.OnDataReceive += DataReceived;
                barcodeHandler.IsAutoReconnect = true;
                barcodeHandler.OnConnectionBreak += BarcodeScannerConnectionEvent;
                barcodeHandler.Start();
                return true;
            }
            catch (Exception ex)
            {
                barcodeHandler = default;
                LogObj.Error("扫码枪初始化失败！" + ex.Message);
                return false;
            }
        }

        /// <summary>
        /// rfid读写器初始化
        /// </summary>
        /// <param name="comm">串口号</param>
        private bool InitRFID(out BarcodeHandler rridHandler, string comm)
        {
            try
            {
                rridHandler = new BarcodeHandler(comm);
                rridHandler.OnDataReceive += RFIDDataReceived;
                rridHandler.IsAutoReconnect = true;
                rridHandler.OnConnectionBreak += RFIDConnectionEvent;
                rridHandler.Start();
                return true;
            }
            catch (Exception ex)
            {
                rridHandler = default;
                LogObj.Error("rfid初始化失败！" + ex.Message);
                return false;
            }
        }

        string LastBarcode = "";
        /// <summary>
        /// 扫码枪接收事件
        /// </summary>
        /// <param name="readBuffer">接收到的字节流</param>
        public void DataReceived(byte[] readBuffer)
        {
            var barcode = Encoding.Default.GetString(readBuffer);
            barcode = Regex.Replace(barcode, @"[\r\n]", "");
            var mesg = "扫描枪扫码："+ barcode;
            MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
            LogObj.Info(mesg);

            /*********************20231211去掉扫码重复校验*********************/
            //if(LastBarcode == barcode)
            //{
            //    LogObj.Debug(DateTime.Now + "   部品码跟上一次部品码一致，不作处理！");
            //    return;
            //}

            LastBarcode = barcode;

            barcode = BarcodeFormat(barcode);
            CheckCode(barcode);
        }

        public string BarcodeFormat(string barcode)
        {
            barcode = barcode.Replace(" ","");
            barcode = barcode.Replace("-", "");

            foreach (var item in PartsSetupList)
            {
                if (barcode.Contains(item.PartsCode))
                {
                    barcode = item.PartsCode;
                    return barcode;
                }
            }
            return "";
        }


        /// <summary>
        /// RFID接收事件
        /// </summary>
        /// <param name="readBuffer">接收到的字节流</param>
        public void RFIDDataReceived(byte[] readBuffer)
        {
            //读取出来数字1到9
            var barcode = Encoding.Default.GetString(readBuffer);
            barcode = Regex.Replace(barcode, @"[\r\n]", "");
            var mesg = "RFID：" + barcode;
            MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
            LogObj.Info(mesg);

            LastBarcode = barcode;

            barcode = BarcodeFormat(barcode);
            CheckRfidCode(barcode);
        }

        /// <summary>
        /// 检验 rfid内容 是否匹配
        /// </summary>
        /// <param name="code"></param>
        public void CheckRfidCode(string code)
        {
            //遍历前面扫码枪扫出来对应的连番，看看这些连番的顺序是否跟rfid的数字一样。
            QueueInfoModel item = null;
            var n = 0;
            foreach (var p in CurrentWorkQueues)
            {
                n++;
                if ((p.Status == "work")&&n.ToString()==code)
                {
                    item = p;
                    break;
                }
            }

            //该位置不能放
            if (item==null)
            {
                
                var mes = "连番" + item.Sequence + "(" + item.VIN + ")校验位置NG";
                MesgNotificationEvent?.BeginInvoke(mes, MessageType.Error, null, null);
                LogObj.Error(mes);

                IoCardErrorAction();
                OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                Thread.Sleep(50);
                OnScanInput?.BeginInvoke(code, false, null, null);
                return;
            }

            //该位置可以放当前油箱
            OnScanInput?.BeginInvoke(code, true, null, null);
            item.Status = "ok";
            item.CompleteDate = DateTime.Now;
            item.SyncFlag = 2;

            queueInfoBLL.Update(item);

            //读rfid设备的逻辑
            if (SysSetup.WorkType == "batch")
            {
                Task.Run(async delegate
                {
                    await Task.Delay(Config.ClearDelayTime);   //清空延时时间

                    //判断当前页是否已全部完成扫描
                    var count = CurrentWorkQueues.Where(x => x.Status == null || x.Status == "work" || x.Status == "unok").Count();
                    if (count <= 0)
                    {
                        IoCardCompleteAction();
                        CurrentWorkQueues.ForEach(x => { x.IsComplete = true; x.SyncFlag = 2; });
                        var result = queueInfoBLL.UpdateList(CurrentWorkQueues);
                        if (result.IsSuccess)
                        {
                            MesgNotificationEvent?.BeginInvoke("数据保存成功！", MessageType.Info, null, null);
                        }
                        else
                        {
                            LogError($"数据保存失败！{result.Dsca}");
                            MesgNotificationEvent?.BeginInvoke($"数据保存失败！{result.Dsca}", MessageType.Info, null, null);
                        }

                        GetQueueInfo(SysSetup.QueueCount, false);   //当前页完成扫描，获取下一页数据
                        return;
                    }
                    for (int i = 0; i < CurrentWorkQueues.Count; i++)
                    {
                        //把油箱放到九宫格的其中一个格子后，将其他连番状态改成空
                        if (CurrentWorkQueues[i].Status == "work")
                        {
                            CurrentWorkQueues[i].Status = "";
                            break;
                        }
                    }
                    OnScanInput?.BeginInvoke("", true, null, null);
                    OnWorkQueueChange?.BeginInvoke(CurrentWorkQueues, null, null);
                });
            }
            else
            {
                IoCardCompleteAction();

                Task.Factory.StartNew(async () =>
                {
                    await Task.Delay(3000);
                    IoCardJudgeAction();
                });
            }


            var mesg = "连番" + item.Sequence + "(" + item.VIN + ")检验位置OK";
            MesgNotificationEvent?.BeginInvoke(mesg, MessageType.Info, null, null);
            LogObj.Info(mesg);

        }

        /// <summary>
        /// 扫码枪连接状态改变事件
        /// </summary>
        /// <param name="str"></param>
        private void BarcodeScannerConnectionEvent(string str)
        {

        }


        /// <summary>
        /// RFID连接状态改变事件
        /// </summary>
        /// <param name="str"></param>
        private void RFIDConnectionEvent(string str)
        {

        }

        /// <summary>
        /// 初始化端末
        /// </summary>
        public bool InitTria(out TriaHandler handler,int logicLength,string triaIp,int triaPort)
        {
            try
            {
                LogObj.Info("初始化端末...");
                LogObj.Info($"连接{triaIp}:{triaPort}...");
                handler = new TriaHandler(triaIp, triaPort);
                handler.SetLogicLength(logicLength);
                handler.OnResolve += OnTriaDataResolve;
                handler.Start();
                LogObj.Info("端末初始化成功!");
                return true;
            }
            catch(Exception ex)
            {
                LogObj.Error("端末初始化失败："+ex.Message);
                handler = default;
                return false;
            }
        }

        /// <summary>
        /// Tria数据处理队列
        /// </summary>
        public void TriaDataQueueResolve()
        {
            Thread thread = new Thread(() =>
            {
                LogObj.Info("Tria数据处理线程启动!");
                while (true)
                {
                    if (!TriaQueue.IsEmpty)
                    {
                        string data;
                        TriaQueue.TryDequeue(out data);
                        if (data != null)
                        {
                            try
                            {
                                // 先解析VinNo,然后通过VinNo去队列表找该数据是否存在
                                try
                                {
                                    QueueInfoModel queueInfo = ParseQueueInfo(data);
                                    // 插入一条数据到报文历史记录表
                                    SaveReceivesMessage(data, queueInfo);
                                }
                                catch (Exception)
                                {
                                    receivesMessageBLL.Add(new ReceivesMessageModel { CreatedDate = DateTime.Now, ReceivesMessage = data, Point = "Error" });
                                }
                            }
                            catch (Exception ex)
                            {
                                LogObj.Error(ExceptionType.BusinessException, ex, "处理接收数据异常!");
                            }
                        }
                        Thread.Sleep(100);
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
            );
            thread.IsBackground = true;
            thread.Start();
        }

        /// <summary>
        /// 接收Tria数据的事件
        /// </summary>
        /// <param name="data">Tria数据</param>
        /// <param name="model">Tria对象</param>
        /// <param name="result">Tria数据的处理结果</param>
        public void OnTriaDataResolve(string data, TriaModel model, TriaProcessResult result)
        {
            try
            {
                LogObj.Debug(DateTime.Now + "  端末接收数据："+ data);
                TriaQueue.Enqueue(data);
            }
            catch (Exception ex)
            {
                LogObj.Error(ExceptionType.BusinessException, ex, "接收数据异常!");
            }
        }

        /// <summary>
        /// 保存报文历史数据
        /// </summary>
        /// <param name="data">Tria数据</param>
        /// <param name="queueInfo"></param>
        public void SaveReceivesMessage(string data, QueueInfoModel queueInfo)
        {
            try
            {
                if (null == queueInfo)
                {
                    receivesMessageBLL.Add(new ReceivesMessageModel { CreatedDate = DateTime.Now, ReceivesMessage = data, Point = "Error" });
                    return;
                }
                string point = data.Substring(Config.PointPosition, Config.PointLength);
                if (point != "H1" && point != "H0" && point != "N0") point = "Error";
                receivesMessageBLL.Add(new ReceivesMessageModel
                {
                    CreatedDate = DateTime.Now,
                    ReceivesMessage = data,
                    Sequence = queueInfo.Sequence,
                    BodyNum = queueInfo.BodyNum,
                    VIN = queueInfo.VIN,
                    Point = point,
                    LittleTime = DateTime.Now,
                    CarModelCode = queueInfo.CarModelCode
                });
                if (queueInfo.ID == 0)
                {
                    queueInfoBLL.Add(queueInfo);
                }
                else
                {
                    queueInfoBLL.Update(queueInfo);
                    LogObj.Error($"队列重复发送![{queueInfo.VIN}]");
                }

                GetQueueInfo(SysSetup.QueueCount, false);
            }
            catch (Exception ex)
            {
                LogObj.Error(ExceptionType.BusinessException, ex, $"保存数据出错![{data}]");
            }
        }

        private object lockObj;
        /// <summary>
        /// 解析队列表数据
        /// </summary>
        /// <param name="data">Tria数据</param>
        /// <returns></returns>
        public QueueInfoModel ParseQueueInfo(string data)
        {
            try
            {
                string vinNo = data.Substring(Config.VinNoPosition, Config.VinNoLength);
                string point = data.Substring(Config.PointPosition, Config.PointLength);
                QueueInfoModel model;
                // 防止下发速度过快
                lock (lockObj)
                {
                    model = queueInfoBLL.GetQueueInfoModelByVin(vinNo);
                }
                if (model == null)
                {
                    var sequence = int.Parse(data.Substring(Config.SequencePosition, Config.SequenceLength));
                    var bodyNum = data.Substring(Config.CarBodyNoPosition, Config.CarBodyNoLength);
                    model = new QueueInfoModel
                    {
                        VIN = vinNo,
                        Sequence = sequence,
                        BodyNum = bodyNum,
                        CarModelCode = Config.CarModelCodeLength > 0 ? data.Substring(Config.CarModelCodePosition, Config.CarModelCodeLength):null
                    };
                }
                // 报文中的时间
                //DateTime dateTime = ToDateTime(data.Substring(Config.TimePosition, Config.TimeLength), Config.TimeLength);
                if ("H1" == point.ToUpper())
                {
                    model.EnqueueDate = DateTime.Now;
                }
                else if ("N0" == point.ToUpper())
                {
                    model.DeQueueDate = DateTime.Now;
                }
                else if ("H0" == point.ToUpper())
                {
                    model.CreatedDate = DateTime.Now;
                }
                else
                {
                    return null;
                }
                var code = vinNo.Substring(7, 1);
                var productionModel = productionModelsBLL.GetModelByModelCode(code);
                if (productionModel == null)
                {
                    model.VehicleModel = "";
                }
                else
                {
                    model.VehicleModel = productionModel != null ? productionModel.ModelName : "";
                }

                var partCode = data.Substring(Config.PartsCodePosition, 1);
                var partSet = partsSetupBLL.GetPartsSetupByCode(partCode);
                if(partSet != null)
                {
                    model.DisplayCode = partSet.DisplayCode;
                    model.CarModelCode = partSet.CarCode;
                    if (SysSetup.CheckType == "PartsCode")
                    {
                        model.PartsCode = partSet.PartsCode;
                    }
                    else if (SysSetup.CheckType == "Mark")
                    {
                        model.Mark = partSet.Mark;
                    }
                }else
                {
                    return default;
                }
                return model;
            }
            catch (Exception ex)
            {
                LogObj.Error(ExceptionType.BusinessException, ex);
                return null;
            }
        }

        /// <summary>
        /// 关闭软件前动作
        /// </summary>
        public void Close()
        {
            IoCardCloseAction();
        }

        /// <summary>
        /// 转换时间
        /// </summary>
        /// <param name="strDate">yyyyMMddHHmm的字符串</param>
        public DateTime ToDateTime(string strDate, int timeLength)
        {
            try
            {
                CultureInfo ci = CultureInfo.CreateSpecificCulture("zh-cn");
                if (timeLength == 12)
                    return DateTime.ParseExact(strDate, "yyyyMMddHHmm", ci);
                else if (timeLength == 14)
                    return DateTime.ParseExact(strDate, "yyyyMMddHHmmss", ci);
                else
                    return DateTime.Now;
            }
            catch (Exception ex)
            {
                LogObj.Error(ExceptionType.BusinessException, ex, "转换时间失败!");
                return DateTime.Parse("1970-01-01");
            }
        }

        public void LogInfo(string mesg)
        {
            LogObj.Info(mesg);
        }
        public void LogError(string mesg)
        {
            LogObj.Error(mesg);
        }

        public void LogDebug(string mesg)
        {
            LogObj.Debug(mesg);
        }
    }
}
